package br.mikhas.container.application;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import br.mikhas.container.config.BeanDefinition;
import br.mikhas.container.config.BeanDefinitionProvider;
import br.mikhas.container.factory.IOCContainerException;
import br.mikhas.container.factory.InitializingBeanFactory;
import br.mikhas.container.factory.PrototypeScope;
import br.mikhas.container.factory.Scope;
import br.mikhas.util.Assert;

/**
 * Basic implementation of an {@link ApplicationContext} to be used as base to
 * other contexts.
 * <p>
 * It implements the most basic application context methods.
 * 
 * @author Mikhail Domanoski
 * 
 */
public abstract class AbstractApplicationContext extends
		InitializingBeanFactory implements ApplicationContext {

	private static final Logger log = LoggerFactory
			.getLogger(AbstractApplicationContext.class);

	private static final boolean debug = log.isDebugEnabled();

	protected Scope applicationScope;

	protected BeanDefinitionProvider definitionProvider;

	@Override
	public final void initializeContext() {
		log.info("Initializing Application Context");

		if (!this.containsScope(PrototypeScope.PROTOTYPE_SCOPE))
			this.registerScope(new PrototypeScope());

		if (!this.containsScope(ApplicationScope.APPLICATION_SCOPE)) {
			this.applicationScope = new ApplicationScope();
			this.registerScope(applicationScope);
		}

		BeanDefinitionProvider resourceProvider = this.getResourceProvider();

		if (resourceProvider == null) {
			throw new IOCContainerException(
					"A ResourceDefinitionProvider must be providen to the application context.");
		}

		if (debug)
			log.debug("Getting resource definition from provider: "
					+ resourceProvider);

		List<BeanDefinition> resources = resourceProvider
				.listResourceDefinition();

		this.registerDefinitions(resources);

		this.initializeScope(ApplicationScope.APPLICATION_SCOPE);
	}

	@Override
	public BeanDefinitionProvider getResourceProvider() {
		return this.definitionProvider;
	}

	@Override
	public void setResourceProvider(BeanDefinitionProvider provider) {
		Assert.notNull(provider);
		this.definitionProvider = provider;
	}

}
